#!/usr/bin/env python
# -*- coding: utf-8 -*-
###########################################################################
#   Copyright (C) 2008 by Serj Poltavsky                                  #
#   serge.uliss at gmail.com                                              #
#                                                                         #
#   This program is free software; you can redistribute it and/or modify  #
#   it under the terms of the GNU General Public License as published by  #
#   the Free Software Foundation; either version 3 of the License, or     #
#   (at your option) any later version.                                   #
#                                                                         #
#   This program is distributed in the hope that it will be useful,       #
#   but WITHOUT ANY WARRANTY; without even the implied warranty of        #
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
#   GNU General Public License for more details.                          #
#                                                                         #
#   You should have received a copy of the GNU General Public License     #
#   along with this program. If not, see <http://www.gnu.org/licenses/>   #
###########################################################################

class DvdFormat(object):
    __map = {
        'pal' : {
            'fps' : 25.0,
            'vbitrate' : 9800,
            'codecs' : ['ac3', 'pcm', 'mp2'],
            'sizes' : [(720, 576), (704, 576), (352, 576)]
        },
        'ntsc' : {
            'fps' : 29.97,
            'vbitrate' : 9800,
            'codecs' : ['ac3', 'pcm'],
            'sizes' : [(720, 480), (704, 480), (352, 480)]
        }
    }

    def __init__(self, format, size = None, aspect = (4,3)):
        self.set_format(format)
        self.set_size(size)
        self.set_aspect(aspect)

    ''' Checks if dvd format is widescreen '''
    def is_widescreen(self):
        return self.__aspect == (16, 9)

    ''' Returns video format aspect ration. for ex. (4, 3) '''
    def get_aspect(self):
        return self.__aspect

    ''' Returns list of audio codecs suiteable for dvd '''
    def get_codecs(self):
        return self.__map[self.__format]['codecs']

    ''' Returns 'pal' or 'ntsc' value '''
    def get_format(self):
        return self.__format

    ''' Returns video frames per sec value '''
    def get_fps(self):
        return self.__map[self.__format]['fps']

    ''' Returns audio samplerate for dvd '''
    def get_samplerate(self):
        return 48000

    ''' Returns dvd frame size. ex. (720, 576) '''
    def get_size(self):
        return self.__size

    def set_aspect(self, aspect):
        if aspect == (16, 9):
            if self.__map[self.__format]['sizes'][0] == self.__size:
                self.__aspect = aspect
            else:
                raise ValueError('Given aspect %s incapatible with video size %s' % (str(aspect), str(self.__size)))
        elif self.valid_aspect(aspect):
            self.__aspect = aspect
        else:
            raise ValueError('Wrong aspect given: %s' % str(aspect))

    def set_format(self, format):
        if not DvdFormat.valid_format(format):
            raise ValueError('Invalid video format: %s' % str(format))
        self.__format = format

    def set_size(self, size):
        if size is None:
            self.__size = self.__map[self.__format]['sizes'][0]
        elif self.valid_size(self.format, size):
            self.__size = size
        else:
            raise ValueError('Wrong video size given: %s' % str(size))

    aspect = property(get_aspect, set_aspect)
    codecs = property(get_codecs)
    format = property(get_format, set_format)
    fps = property(get_fps)
    samplerate = property(get_samplerate)
    size =   property(get_size, set_size)

    @staticmethod
    def ntsc():
        return DvdFormat('ntsc')

    @staticmethod
    def pal():
        return DvdFormat('pal')

    @staticmethod
    def valid_aspect(aspect):
        return aspect in [(4,3), (16, 9)]

    @staticmethod
    def valid_codec(format, codec):
        return DvdFormat.valid_format(format) and codec.lower() in DvdFormat.__map[format]['codecs']

    @staticmethod
    def valid_format(format):
        return str(format).lower() in ('pal', 'ntsc')

    @staticmethod
    def valid_samplerate(rate):
        return rate == 48000

    @staticmethod
    def valid_size(format, size): 
        return DvdFormat.valid_format(format) and size in DvdFormat.__map[format]['sizes']